package Market;

import java.util.ArrayList;

import edu.iastate.jrelm.core.SimpleAction;
import edu.iastate.jrelm.rl.rotherev.REPolicy;
import edu.iastate.jrelm.core.JReLMAgent;
import edu.iastate.jrelm.rl.ReinforcementLearner;
import edu.iastate.jrelm.rl.SimpleStatelessLearner;
import edu.iastate.jrelm.rl.rotherev.variant.VREParameters;


import sim.engine.*;


public class GenCo implements Steppable
   {
	private static final long serialVersionUID = 6628525522939315274L;


	private double aR;
	private double bR;
	private double CapRL;
	private double CapRU;
	private double[] RSupplyOffer;   // Reported supply offer (aR,bR,CapRL,CapRU), strategic
	
	private double aT; 
	private double bT; 
	private double CapTU;
	private double CapTL;
	
	private double SS = 0.05; // slope start
	private double[] TSupplyOffer;  // True supply offer (a,b,CapTL,CapTU)

	private double l;
	private double u;
	private double lR;
	private double uR;
	private double us;
	
	 double RCapL;
	 double RCapU;
	 double RIL;
	 double RIU;
	 
	 double M1;
	 double M2;
	 double M3;
	 
	double RIMaxL;
	double RIMaxU;
	double RIMinC;
	 
	 double Propensity;
	 double Cooling;
	 double Recency;
	 double Experimentation;
	 
	 double RewardSelection;
	
	 ArrayList ADList; //action domain
	
	private double[] alpha;
	double M;
	
											/** number of GenCos */
	private int ii;
	
	Market market;
	boolean Switch;
	
	  // JReLM component
	  private SimpleStatelessLearner Learner;
	  int RandomSeed;

//----Constructor------------------------------------------------------------------------------------	
	public GenCo(double[][] gencodata, double[][] learningdata, int i, int randomseed, sw, Market mkt){
	
		market = mkt;
		ii = i;
		RandomSeed = randomseed;
		Switch = sw;
		
		aT     = gencodata[ii][3];
		bT     = gencodata[ii][4];
		CapTL  = gencodata[ii][5];
		CapTU  = gencodata[ii][6];
	
		
		Propensity  	= learningdata[ii][0];
		Cooling  		= learningdata[ii][1];
		Recency         = learningdata[ii][2];
		Experimentation = learningdata[ii][3];
		
		M1  			= learningdata[ii][4];
		M2  			= learningdata[ii][5];
		M3  			= learningdata[ii][6];
		RIMaxL   		= learningdata[ii][7];
		RIMaxU   		= learningdata[ii][8];
		RIMinC  		= learningdata[ii][9];
		SS   			= learningdata[ii][10];
		RewardSelection = learningdata[ii][11];
	}
	
	public GenCo(){
		
		
	}
	

	//-----------------------------------------------------------------------------------------------------------------------------------------
    public void step(SimState state)
        {
    	 // ActionDomainConstruction();
    	 // ReportedSupplyOfferValidation(0.10, 0.20, 1.00);

    	
    	VREParameters learningParams = new VREParameters(Cooling, Experimentation, Propensity, Recency, RandomSeed);	    	
    	
    	if(!Switch){
    	
    	ADList = ActionDomainConstruction();
    	Learner = new SimpleStatelessLearner(learningParams, ADList);
    	
        double[] Triplet = (double[]) Learner.chooseActionRaw();
        
        aR    = Triplet[0];
        bR    = Triplet[1];        
        CapRU = Triplet[2];
        CapRU = CapTU;
    	
    	
    	
    	market.addAactionDomain(ADList);
    	market.setLearner(Learner);
    	market.addGenCo(this);
    	
    	SetRSupplyOffer();
    	setTSupplyOffer();
    	
    	market.setRSupplyOffer(RSupplyOffer, ii);
    	market.setTSupplyOffer(TSupplyOffer, ii);}
    	
    	else{
    		
    		
    	}
    	
    	
    	
    	//for (int k=0;k<4; k++){
    	//System.out.println(TSupplyOffer[k]);
    	//}
        }
    
//------------------------------------------------------------------------------------------------------------------------------------------    
/** The function checks whether reported supply offer is feasible or not 
 * @see <f/> DynTestAMES.JSLT.pdf (pg 34)  */    
    private void ReportedSupplyOfferValidation(double x, double y, double z) {
    	

    	
    	//RIL = x;
    	//RIU = y;
    	//RCapU = z;
    	
    	RCapL = CapTL/CapTU;
    	
//Step 0
   CapRL = CapTL;
   CapRL = RCapL*CapTU;
   CapRU = RCapU*(CapTU-CapTL)+CapTL;  

   l = aT+2*bT*CapTL;
   u = aT+2*bT*CapRU;

//Step 1
   lR = l/(1-RIL);
   
//Step2
   if(u > lR) { us = u; }
	   
     else {us = lR+SS;}
	  
//Step3
   uR = us/(1-RIU);
   
//Step4
   bR = 0.5*(uR-lR)/(CapRU-CapRL);
   
//Step5
   aR = lR-2*bR*CapTL;
   
   System.out.println("a_reported = " + aR);
   System.out.println("b_reported = " + bR);
    }
    
//------------------------------------------------------------------------------------------------------------------------------------------    

private ArrayList ActionDomainConstruction(){
	

    
	ArrayList ADMat = new ArrayList();
    
    M = M1 * M2 * M3;


	
	
	double Inc1 = RIMaxL/(M1 - 1);
	double Inc2 = RIMaxU/(M2 - 1);
	double Inc3 = (1-RIMinC)/(M3-1);
	
	for (double i = 0; i <= RIMaxL; i = i+Inc1){
		for (double j = 0; j <= RIMaxU; j = j+Inc2 ){
			for(double k = 1-RIMinC; k >= 0; k = k-Inc3){  
				
	            alpha = new double[3]; // initialize triplet to zeros
	            alpha[0] = i; 
	            alpha[1] = j; 
	            alpha[2] = k +RIMinC ; 
    
	            
	            ADMat.add(alpha);
	            
	           // System.out.println(alpha[0] + "   " + alpha[1] + "   " + alpha[2]);
	            
		
			}		
    	}
	}
	
	return ADMat;
}

public void SetRSupplyOffer(){

	RSupplyOffer = new double[4];
	
		RSupplyOffer[0] = aR;
		RSupplyOffer[1] = bR;
		RSupplyOffer[2] = CapRL;
		RSupplyOffer[3] = CapRU;
	
  }
    

public void setTSupplyOffer(){

	TSupplyOffer = new double[4];
	
	TSupplyOffer[0]=aT;
	TSupplyOffer[1]=bT;
	TSupplyOffer[2]=CapTL;
	TSupplyOffer[3]=CapTU;
	
	//System.out.println(TSupplyOffer[1]);
    ; 
  }
	
   } 
   














